package p.ithorns.sample.refresh;

import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * SpringValueProcessor
 *
 * @author HtL
 * @date 2025/3/14 17:40
 * @since 1.0.0
 */
@Component
public class SpringValueProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> aClass = bean.getClass();
        List<ValueHolder> annotates = getClassValueHolders(aClass, bean, beanName);
        for (ValueHolder vh : annotates) {
            registerValueHolder(vh);
        }
        return bean;
    }

    private void registerValueHolder(ValueHolder vh) {
        ConfigContext.getValueHolders().put(vh.getKey(), vh);
    }

    private List<ValueHolder> getClassValueHolders(Class<?> clazz, Object bean, String beanName) {
        final List<ValueHolder> valueHolders = new ArrayList<>();

       //  Field[] fields = getFields(bean);
        final List<Field> fields = new LinkedList<>();
        ReflectionUtils.doWithFields(clazz, fields::add);
        // 获取类中的所有字段
        for (Field field : fields) {
            // 检查字段是否被 @Value 注解
            if (AnnotatedElementUtils.hasAnnotation(field, Value.class)) {
                Value anno = field.getAnnotation(Value.class);
                String placeholder = anno.value();
                String key = extractKey(placeholder);
                valueHolders.add(new ValueHolder(key, placeholder, bean, beanName, field));
            }
        }

        final List<Method> methods = new LinkedList<>();
        ReflectionUtils.doWithMethods(clazz, methods::add);
        // 获取类中的所有方法
        for (Method method : methods) {
            // 检查方法是否被 @Value 注解
            if (AnnotatedElementUtils.hasAnnotation(method, Value.class)) {
                Value anno = method.getAnnotation(Value.class);
                String placeholder = anno.value();
                String key = extractKey(placeholder);
                valueHolders.add(new ValueHolder(key, placeholder, bean, beanName, method));
            }
        }

        return valueHolders;
    }



    private static String extractKey(String expression) {
        // 使用正则表达式匹配 ${...} 中的内容
        Pattern pattern = Pattern.compile("\\$\\{(.*?)}");
        Matcher matcher = pattern.matcher(expression);
        if (matcher.find()) {
            String matchedContent = matcher.group(1);
            // 如果有默认值，分割并取第一个部分
            if (matchedContent.contains(":")) {
                return matchedContent.split(":")[0];
            }
            return matchedContent;
        }
        return null;
    }


    private Field[] getFields(Object bean) {
        if (null == bean) {
            return new Field[0];
        }

        Class<?> targetClass = bean.getClass();
        if (targetClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)
                || AopUtils.isCglibProxy(bean)
                || AopUtils.isJdkDynamicProxy(bean)) {
            targetClass = AopUtils.getTargetClass(bean).getSuperclass();
        }
        return targetClass.getDeclaredFields();
    }

}